/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.bomt.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.bomt.common.enums.BizFileTypeEnum;
import com.comac.ins.bomt.domain.*;
import com.comac.ins.bomt.domain.bo.OriginalBomDetailQuery;
import com.comac.ins.bomt.domain.vo.*;
import com.comac.ins.bomt.mapper.*;
import com.comac.ins.bomt.service.BomQueryServiceV2;
import com.comac.ins.common.core.domain.model.LoginUser;
import com.comac.ins.common.biz.utils.BizAssertUtil;
import com.comac.ins.common.json.utils.JsonUtils;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zhanghongyi
 * @date 2024/8/6 16:32
 * @description BomQueryService
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class BomQueryServiceV2Impl implements BomQueryServiceV2 {

    private final BomtBizFileMapper bomtBizFileMapper;

    private final BomtOriginalBomV2InfoMapper originalBomV2InfoMapper;

    private final BomtOriginalBomV2DetailMapper originalBomV2DetailMapper;

    private final BomtStandardBomV2InfoMapper standardBomV2InfoMapper;

    private final BomtStandardBomV2DetailMapper standardBomV2DetailMapper;

    private final BomtStrengthBomV2InfoMapper strengthBomV2InfoMapper;

    private final BomtStrengthBomV2DetailMapper strengthBomV2DetailMapper;


    @Override
    public TableDataInfo<OriginalBomV2InfoVo> listOriginalByPage(LoginUser loginUser, String aircraftModel,String track, PageQuery pageQuery) {
        LambdaQueryWrapper<OriginalBomV2Info> queryWrapper = new LambdaQueryWrapper<OriginalBomV2Info>()
            .eq(OriginalBomV2Info::getAircraftModel, aircraftModel);
        if(StringUtils.isNotBlank(track)){
            queryWrapper.eq(OriginalBomV2Info::getTrack, track);
        }
        Page<OriginalBomV2InfoVo> page = originalBomV2InfoMapper.selectVoPage(pageQuery.build(), queryWrapper);
        return TableDataInfo.build(page);
    }
    @Override
    public OriginalBomV2InfoVo queryOriginalBomInfoVoById(LoginUser loginUser, Long id) {
        OriginalBomV2InfoVo info = originalBomV2InfoMapper.selectVoById(id);
        return info;
    }

    @Override
    public TableDataInfo<StandardBomV2InfoVo> listStandardByPage(LoginUser loginUser,String aircraftModel,String track, String section,String mainSection, PageQuery pageQuery) {
        pageQuery.setOrderByColumn("group_type,sub_group_type,update_time");
        LambdaQueryWrapper<StandardBomV2Info> queryWrapper = new LambdaQueryWrapper<StandardBomV2Info>()
            .eq(StandardBomV2Info::getAircraftModel, aircraftModel)
            .eq(StandardBomV2Info::getTrack, track);
        if(StringUtils.isNotBlank(section)){
            queryWrapper.eq(StandardBomV2Info::getSection, section);
        }
        if(StringUtils.isNotBlank(mainSection)){
            queryWrapper.eq(StandardBomV2Info::getMainSection, mainSection);
        }
        Page<StandardBomV2InfoVo> page = standardBomV2InfoMapper.selectVoPage(pageQuery.build(), queryWrapper);
        return TableDataInfo.build(page);
    }
    @Override
    public TableDataInfo<StrengthBomV2InfoVo> listStrengthByPage(LoginUser loginUser,String aircraftModel,String track,String section,String mainSection,  PageQuery pageQuery) {
        pageQuery.setOrderByColumn("group_type,sub_group_type,update_time");
        LambdaQueryWrapper<StrengthBomV2Info> queryWrapper = new LambdaQueryWrapper<StrengthBomV2Info>()
            .eq(StrengthBomV2Info::getAircraftModel, aircraftModel)
            .eq(StrengthBomV2Info::getTrack, track);
        if(StringUtils.isNotBlank(section)){
            queryWrapper.eq(StrengthBomV2Info::getSection, section);
        }
        if(StringUtils.isNotBlank(mainSection)){
            queryWrapper.eq(StrengthBomV2Info::getMainSection, mainSection);
        }
        Page<StrengthBomV2InfoVo> page = strengthBomV2InfoMapper.selectVoPage(pageQuery.build(), queryWrapper);
        return TableDataInfo.build(page);
    }

    public TableDataInfo<DetailOriginalV2BomVo> queryOriginalDetailByPage(LoginUser loginUser, OriginalBomDetailQuery detailQuery){
        QueryWrapper<DetailOriginalV2Bom> wrapper = new QueryWrapper<>();
        wrapper.eq("aircraft_model", detailQuery.getAircraftModel());
        wrapper.eq("track", detailQuery.getTrack());
        wrapper.eq("sub_track", detailQuery.getSubTrack());
        if (StringUtils.isNotBlank(detailQuery.getCode())) {
            wrapper.eq("code", detailQuery.getCode());
        }
        if (StringUtils.isNotBlank(detailQuery.getLevel())) {
            wrapper.eq("level", detailQuery.getLevel());
        }
        if (StringUtils.isNotBlank(detailQuery.getVersion())) {
            wrapper.eq("version", detailQuery.getVersion());
        }
        if (StringUtils.isNotBlank(detailQuery.getSectionName())) {
            wrapper.like("section", detailQuery.getSectionName());
        }
        if (StringUtils.isNotBlank(detailQuery.getName())) {
            wrapper.like("name", detailQuery.getName());
        }
        wrapper.orderByAsc("ord");
        Page<DetailOriginalV2BomVo> page = originalBomV2DetailMapper.selectVoPage(detailQuery.build(), wrapper);
        return TableDataInfo.build(page);
    }

    public TableDataInfo<DetailStandardV2BomVo> queryStandardDetailByPage(LoginUser loginUser,PageQuery pageQuery,String aircraftModel,Long infoId,String name, String code){
        QueryWrapper<DetailStandardV2Bom> wrapper = new QueryWrapper<>();
        wrapper.eq("aircraft_model", aircraftModel);
        wrapper.eq("info_id", infoId);
        if (StringUtils.isNotBlank(code)) {
            wrapper.eq("code", code);
        }
        if (StringUtils.isNotBlank(name)) {
            wrapper.like("name", name);
        }
        wrapper.orderByAsc("ord");
        Page<DetailStandardV2BomVo> page = standardBomV2DetailMapper.selectVoPage(pageQuery.build(), wrapper);
        return TableDataInfo.build(page);
    }
    public List<StrengthBomV2Info> queryStrengthInfos(LoginUser loginUser,String aircraftModel,String track,String groupType){
        QueryWrapper<StrengthBomV2Info> wrapper = new QueryWrapper<>();
        wrapper.eq("aircraft_model", aircraftModel);
        wrapper.eq("track", track);
        if(!StringUtils.equalsIgnoreCase("ALL", groupType)){
            wrapper.eq("group_type", groupType);
            wrapper.last("limit 1");
        }
        wrapper.orderByDesc("update_time");
        return  strengthBomV2InfoMapper.selectList(wrapper);
    }

    public List<DetailStrengthV2Bom> queryStrengthDetail(LoginUser loginUser,String aircraftModel,String track,String groupType){
        QueryWrapper<DetailStrengthV2Bom> wrapper = new QueryWrapper<>();
        wrapper.eq("aircraft_model", aircraftModel);
        wrapper.eq("track", track);
        wrapper.eq("group_type", groupType);
        wrapper.orderByAsc("ord");
        List<DetailStrengthV2Bom> data = strengthBomV2DetailMapper.selectList(wrapper);
        return data;
    }
    public TableDataInfo<DetailStrengthV2BomVo> queryStrengthDetailByPage(LoginUser loginUser,PageQuery pageQuery,String aircraftModel,String track,String groupType,String name, String code){
        QueryWrapper<DetailStrengthV2Bom> wrapper = new QueryWrapper<>();
        wrapper.eq("aircraft_model", aircraftModel);
        wrapper.eq("track", track);
        wrapper.eq("group_type", groupType);
        if (StringUtils.isNotBlank(code)) {
            wrapper.eq("code", code);
        }
        if (StringUtils.isNotBlank(name)) {
            wrapper.like("name", name);
        }
        wrapper.orderByAsc(Arrays.asList("ord","code","version","version_num"));
        Page<DetailStrengthV2BomVo> page = strengthBomV2DetailMapper.selectVoPage(pageQuery.build(), wrapper);
        Page<DetailStrengthV2BomVo> fillPage = fillStrengthGroupInfo(page, pageQuery, wrapper);
        return TableDataInfo.build(fillPage);
    }

    @Override
    public Map<String, List<TrackGroupInfoVo>> listAllTrackInfo(LoginUser loginUser, String aircraftModel) {
        QueryWrapper<OriginalBomV2Info> originalWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(aircraftModel)) {
            originalWrapper.eq("aircraft_model", aircraftModel);
        }
        originalWrapper.orderByDesc("update_time");
        originalWrapper.last("limit 3000");
        List<OriginalBomV2Info> originalBomInfoList = originalBomV2InfoMapper.selectList(originalWrapper);
        QueryWrapper<BizFile> bizFileWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(aircraftModel)) {
            bizFileWrapper.eq("aircraft_model", aircraftModel);
        }
        bizFileWrapper.eq("file_type", BizFileTypeEnum.INIT.getCode());
        bizFileWrapper.ne("sub_track", "");
        List<BizFile> bizFileList = bomtBizFileMapper.selectList(bizFileWrapper);

        Set<String> aircraftModels = originalBomInfoList.stream().map(OriginalBomV2Info::getAircraftModel).collect(Collectors.toSet());
        aircraftModels.addAll(bizFileList.stream().map(BizFile::getAircraftModel).collect(Collectors.toSet()));
        Map<String,List<TrackGroupInfoVo>> result = new HashMap<>();
        for (String aircraft : aircraftModels) {
            Map<String, List<TrackInfoVo>> trackInfoGroupMap = originalBomInfoList.stream().filter(bomInfo -> StringUtils.equals(aircraft, bomInfo.getAircraftModel())).map(bomInfo -> {
                TrackInfoVo trackInfo = new TrackInfoVo();
                trackInfo.setSubTrack(bomInfo.getSubTrack());
                trackInfo.setTrack(bomInfo.getTrack());
                trackInfo.setAircraftModel(bomInfo.getAircraftModel());
                trackInfo.setDesc(bomInfo.getTrackDesc());
                return trackInfo;
            }).collect(Collectors.groupingBy(TrackInfoVo::getTrack));
            for (BizFile bizFile : bizFileList) {
                if (StringUtils.equals(aircraft, bizFile.getAircraftModel())) {
                    TrackInfoVo trackInfo = new TrackInfoVo();
                    trackInfo.setSubTrack(bizFile.getSubTrack());
                    trackInfo.setTrack(bizFile.getTrack());
                    trackInfo.setAircraftModel(bizFile.getAircraftModel());
                    FileExtraInfo fileExtra = JsonUtils.parseObject(bizFile.getExtraInfo(), FileExtraInfo.class);
                    trackInfo.setDesc(null == fileExtra?null:fileExtra.getBatchDesc());
                    List<TrackInfoVo> subTrackList = trackInfoGroupMap.getOrDefault(bizFile.getTrack(), new ArrayList<>());
                    subTrackList.add(trackInfo);
                    trackInfoGroupMap.put(bizFile.getTrack(), subTrackList);
                }
            }
            List<TrackGroupInfoVo> resultItem = trackInfoGroupMap.entrySet().stream().map(entry -> {
                TrackGroupInfoVo groupInfo = new TrackGroupInfoVo();
                groupInfo.setTrack(entry.getKey());
                groupInfo.setLatestSubTrack(entry.getValue().stream().max(Comparator.comparing(TrackInfoVo::getSubTrack)).orElse(new TrackInfoVo()).getSubTrack());
                groupInfo.setTrackInfoVos(entry.getValue());
                return groupInfo;
            }).sorted(Comparator.comparing(TrackGroupInfoVo::getLatestSubTrack, Comparator.reverseOrder())).collect(Collectors.toList());
            log.info("listAllTrackInfo-{}:{}-{}->{}", aircraft, originalBomInfoList.size(),bizFileList.size(), result.size());
            result.put(aircraft, resultItem);
        }
        return result;
    }

    @Override
    public OriginalBomV2Info queryOriginalBomInfo(LoginUser loginUser, String aircraftModel, String track, String subTrack) {
        return originalBomV2InfoMapper.selectOne(new LambdaQueryWrapper<OriginalBomV2Info>()
                .eq(OriginalBomV2Info::getAircraftModel, aircraftModel)
                .eq(OriginalBomV2Info::getTrack, track)
                .eq(OriginalBomV2Info::getSubTrack, subTrack)
                .orderByDesc(OriginalBomV2Info::getUpdateTime)
                .last("limit 1"));
    }

    @Override
    public OriginalBomV2Info queryOriginalBomInfoById(LoginUser loginUser, Long id) {
        return originalBomV2InfoMapper.selectById(id);
    }

    @Override
    public List<StandardBomV2Info> queryStandardBomInfoByIds(LoginUser loginUser, List<Long> ids) {
        return standardBomV2InfoMapper.selectBatchIds(ids);
    }
    @Override
    public List<DetailOriginalV2BomVo> queryOriginalBomDetail(LoginUser loginUser, String aircraftModel, String track, String subTrack) {
        QueryWrapper<DetailOriginalV2Bom> wrapper = new QueryWrapper<>();
        wrapper.eq("aircraft_model", aircraftModel);
        wrapper.eq("track", track);
        wrapper.eq("sub_track", subTrack);
        wrapper.orderByAsc("ord");
        List<DetailOriginalV2BomVo> result = originalBomV2DetailMapper.selectVoList(wrapper);
        BizAssertUtil.notEmpty(result, "original detail not found");
        return result;
    }

    @Override
    public StrengthBomV2Info queryStrengthBomInfoById(LoginUser loginUser, Long id) {
        return strengthBomV2InfoMapper.selectById(id);
    }

    @Override
    public StandardBomV2Info queryStandardBomInfoById(LoginUser loginUser, Long id) {
        return standardBomV2InfoMapper.selectById(id);
    }


    @Override
    public List<DetailStandardV2Bom> queryStandardBomDetailByInfoId(LoginUser loginUser, String aircraftModel, Long infoId) {
        QueryWrapper<DetailStandardV2Bom> wrapper = new QueryWrapper<>();
        wrapper.eq("aircraft_model", aircraftModel);
        wrapper.eq("info_id", infoId);
        wrapper.orderByAsc("ord");
        List<DetailStandardV2Bom> result = standardBomV2DetailMapper.selectList(wrapper);
        BizAssertUtil.notEmpty(result, "original detail not found");
        return result;
    }
    @Override
    public List<DetailStandardV2Bom> queryStandardBomDetail(LoginUser loginUser, String aircraftModel, String track,String subTrack) {
        QueryWrapper<DetailStandardV2Bom> wrapper = new QueryWrapper<>();
        wrapper.eq("aircraft_model", aircraftModel);
        wrapper.eq("track", track);
        wrapper.eq("sub_track", subTrack);
        wrapper.orderByAsc("ord");
        List<DetailStandardV2Bom> result = standardBomV2DetailMapper.selectList(wrapper);
        BizAssertUtil.notEmpty(result, "original detail not found");
        return result;
    }

    private Page<DetailStrengthV2BomVo>  fillStrengthGroupInfo(Page<DetailStrengthV2BomVo> pageData,PageQuery pageQuery,QueryWrapper<DetailStrengthV2Bom> wrapper){
        String groupCode = null;
        String groupName = null;
        String groupVersion = null;
        Integer origPageNum = pageQuery.getPageNum();
        for(DetailStrengthV2BomVo item:pageData.getRecords()){
            if(StringUtils.equals("1",item.getLevel())){
                groupCode = item.getCode();
                groupName = item.getName();
                groupVersion = item.getVersion()+item.getVersionNum();
            }

            while(StringUtils.isBlank(groupCode)&&pageQuery.getPageNum()>1){
                    pageQuery.setPageNum(pageQuery.getPageNum()-1);
                    Page<DetailStrengthV2BomVo> preData = strengthBomV2DetailMapper.selectVoPage(pageQuery.build(), wrapper);
                    for(int i=preData.getRecords().size();i>0;i--){
                        if(StringUtils.equals("1",preData.getRecords().get(i-1).getLevel())){
                            groupCode = preData.getRecords().get(i-1).getCode();
                            groupName = preData.getRecords().get(i-1).getName();
                            groupVersion = preData.getRecords().get(i-1).getVersion()+preData.getRecords().get(i-1).getVersionNum();
                            break;
                        }
                    }
            }
            item.setGroupCode(groupCode);
            item.setGroupName(groupName);
            item.setGroupVersion(groupVersion);
        }
        pageQuery.setPageNum(origPageNum);
        return pageData;
    }
}
